#include <string.h>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

const int N = 1010;
int n, V;
int v[N], w[N];
// int dp[N][N];
int dp[N];


int main() {
    cin >> n >> V;
    for(int i = 0; i < n; i++)
        cin >> v[i] >> w[i];
    
    // 下面是利用滚动数组做优化的写法
    for(int i = 1; i <= n; i++)
        for(int j = v[i - 1]; j <= V; j++)
                dp[j] = max(dp[j], dp[j - v[i - 1]] + w[i - 1]);
    cout << dp[V] << endl;

    memset(dp, 0, sizeof dp);

    for(int j = 1; j <= V; j++)
        dp[j] = -1;

    for(int i = 1; i <= n; i++)
        for(int j = v[i - 1]; j <= V; j++)
            if(dp[j - v[i - 1]] != -1)
                dp[j] = max(dp[j], dp[j - v[i - 1]] + w[i - 1]);
    cout << (dp[V] == -1 ? 0 : dp[V]) << endl;


    // dp[i][j]表示从前i个物品中选，总体积不超过j，此时的最大价值
    // for(int i = 1; i <= n; i++)
    // {
    //     for(int j = 0; j <= V; j++)
    //     {
    //         dp[i][j] = dp[i - 1][j];
    //         if(j >= v[i - 1])
    //             dp[i][j] = max(dp[i][j], dp[i][j - v[i - 1]] + w[i - 1]);
    //     }
    // }
    // cout << dp[n][V] << endl;

    // memset(dp, 0, sizeof dp);

    // // dp[i][j]表示从前i个物品中选，总体积恰好等于j，此时的最大价值
    // // 我们依然规定，当不可能出现恰好凑成等于j的情况时，dp值为-1
    // for(int j = 1; j <= V; j++)
    //     dp[0][j] = -1;

    // for(int i = 1; i <= n; i++)
    // {
    //     for(int j = 0; j <= V; j++)
    //     {
    //         dp[i][j] = dp[i - 1][j];
    //         if(j >= v[i - 1] && dp[i][j - v[i - 1]] != -1)
    //             dp[i][j] = max(dp[i][j], dp[i][j - v[i - 1]] + w[i - 1]);
    //     }
    // }
    // cout << (dp[n][V] == -1 ? 0 : dp[n][V]) << endl;

    return 0;
}